package com.example.demo.controller;

import com.example.demo.entity.UserInfo;
import com.example.demo.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * Created with IntelliJ IDEA.
 * Description:
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService service;

    // JDBC 事务管理器
    @Autowired
    private DataSourceTransactionManager transactionManager;
    // 定义事务属性
    @Autowired
    private TransactionDefinition transactionDefinition;

    // 新增数据
    @RequestMapping("/adduser")
    public Integer addUser(UserInfo userInfo) {
        // 非空校验
        if(userInfo == null || !StringUtils.hasLength(userInfo.getUsername())
                || !StringUtils.hasLength(userInfo.getPassword())) {
            return 0;
        }
        // 1. 开启事务
        TransactionStatus status =
                transactionManager.getTransaction(transactionDefinition);
        Integer result = service.addUser(userInfo);
        log.info("添加 " + result + " 条数据");

        // 2. 回滚事务
        // transactionManager.rollback(status);
        // 3. 提交事务
        transactionManager.commit(status);
        return result;
    }

    // Spring 声明式事务（自动）
    // 对照，新增用户
    @Transactional() // 声明式事务（自动提交）
    @RequestMapping("/adduser2")
    public Integer addUser2(UserInfo userInfo) {
        // 非空校验
        if(userInfo == null || !StringUtils.hasLength(userInfo.getUsername())
                || !StringUtils.hasLength(userInfo.getPassword())) {
            return 0;
        }
        // 1. 会自动开启事务
        Integer result = service.addUser(userInfo);
        log.info("添加 " + result + " 条数据");

        // 2. 如果抛了异常自动回滚事务
        try {
            int test = 10 / 0;
        } catch (Exception e) {
            log.error(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        // 3. 如果没抛异常就自动提交事务
        return result;

    }

    // 七种事务传播机制
    // 第一种，Propagation.REQUIRED
    // 验证：当无父事务时，子事务作为单独的事务执行，即父方法抛出异常，不影响子方法的插入操作
    //      当有父事务时，子事务串入父事务中一起执行，父事务抛出异常，整个事务回滚
    // 验证通过
    @Transactional
    @RequestMapping("/adduser3")
    public Integer adduser3(UserInfo userInfo) {
        if(userInfo == null || !StringUtils.hasLength(userInfo.getUsername())
                || !StringUtils.hasLength(userInfo.getPassword())) {
            return 0;
        }
        Integer result = service.addUser(userInfo);
        log.info("添加 " + result + " 条数据");
        try {
            int test = 10 / 0;
        } catch (Exception e) {
            log.error(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return result;
    }

    // 第二种,SUPPORTS
    // 验证：当无父事务时，子事务以非事务的方式执行，即子事务抛出算术异常，数据新增成功，不进行回滚
    //      当有父事务时，子事务串入父事务中一起执行，任一方法抛出异常，整个事务回滚
    // 测试通过
    // @Transactional
    @RequestMapping("/adduser4")
    public Integer adduser4(UserInfo userInfo) {
        if(userInfo == null || !StringUtils.hasLength(userInfo.getUsername())
                || !StringUtils.hasLength(userInfo.getPassword())) {
            return 0;
        }
        Integer result = service.addUser(userInfo);
        log.info("添加 " + result + " 条数据");
        try {
            int test = 10 / 0;
        } catch (Exception e) {
            log.error(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return result;
    }

    // 第三种，MANDATORY
    // 验证：无父事务时，直接抛出异常
    //      有父事务时，等同于REQUIRED
    // 验证通过
    @Transactional
    @RequestMapping("/adduser5")
    public Integer addUser5(UserInfo userInfo) {
        if(userInfo == null || !StringUtils.hasLength(userInfo.getUsername())
                || !StringUtils.hasLength(userInfo.getPassword())) {
            return 0;
        }
        Integer result = service.addUser(userInfo);
        log.info("添加 " + result + " 条数据");
        try {
            int test = 10 / 0;
        } catch (Exception e) {
            log.error(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return result;
    }

    // 第四种，REQUIRES_NEW
    // 验证：无父事务时，子事务新建事务作为独立事务执行
    //      有父事务时，子事务仍新建事务作为独立事务执行
    // 验证通过
    @Transactional
    @RequestMapping("/adduser6")
    public Integer addUser6(UserInfo userInfo) {
        if(userInfo == null || !StringUtils.hasLength(userInfo.getUsername())
                || !StringUtils.hasLength(userInfo.getPassword())) {
            return 0;
        }
        Integer result = service.addUser(userInfo);
        log.info("添加 " + result + " 条数据");
        try {
            int test = 10 / 0;
        } catch (Exception e) {
            log.error(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return result;
    }

    // 第五种，NOT_SUPPORTED
    // 验证：无父事务时，子事务以非事务的方式运行，同SUPPORTS
    //      有父事务时，把父事务挂起，子事务仍以非事务的方式运行，
    //          如果父事务有异常抛出，父事务回滚，对子事务无影响
    // 验证通过
    @Transactional
    @RequestMapping("/adduser7")
    public Integer addUser7(UserInfo userInfo) {
        if(userInfo == null || !StringUtils.hasLength(userInfo.getUsername())
                || !StringUtils.hasLength(userInfo.getPassword())) {
            return 0;
        }
        Integer result = service.addUser(userInfo);
        log.info("添加 " + result + " 条数据");
        try {
            int test = 10 / 0;
        } catch (Exception e) {
            log.error(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return result;
    }

    // 第六种，NEVER
    // 验证：无父事务时，以非事务的方式运行
    //      有父事务时，子事务抛出异常，如果父事务不处理就导致父事务回滚
    // 验证通过
    @Transactional
    @RequestMapping("/adduser8")
    public Integer addUser8(UserInfo userInfo) {
        if(userInfo == null || !StringUtils.hasLength(userInfo.getUsername())
                || !StringUtils.hasLength(userInfo.getPassword())) {
            return 0;
        }
        Integer result = null;
        try {
            result = service.addUser(userInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("添加 " + result + " 条数据");
//        try {
//            int test = 10 / 0;
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        return result;
    }

    // 第七种，NEVER
    // 验证：无父事务时，子事务创建独立事务，等同于Propagation.REQUIRED
    //      有父事务时，嵌套在父事务之内，即父事务抛出异常，整个回滚，子事务抛出异常，子事务回滚
    // 验证通过
    // @Transactional
    @RequestMapping("/adduser9")
    public Integer addUser9(UserInfo userInfo) {
        if(userInfo == null || !StringUtils.hasLength(userInfo.getUsername())
                || !StringUtils.hasLength(userInfo.getPassword())) {
            return 0;
        }
        Integer result = null;
        result = service.addUser(userInfo);
        log.info("添加 " + result + " 条数据");
        int test = 10 / 0;
        return result;
    }
}
